package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dto.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.minio.MinIOService;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.media.dto.ArticleDto;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.entity.WmChannel;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmSensitive;
import com.heima.media.entity.WmUser;
import com.heima.media.feign.ArticleFeign;
import com.heima.media.service.*;
import org.apache.commons.io.IOUtils;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @author zsk
 * @create 2022-04-13-17:45
 */
@Service
public class IAuditServiceImpl implements IAuditService {

    //依赖注入阿里云审核
    @Autowired
    private GreenTextScan textScan;//文本审核

    @Autowired
    private GreenImageScan imageScan;//图片审核

    @Autowired
    private IWmNewsService wmNewsService;


    @Autowired
    private IWmUserService userService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 文章审核
     *
     * @param wmNews
     */
    @Override
    @Async//异步调用
    public void audit(WmNews wmNews) {

        System.out.println(Thread.currentThread().getName() + " 开始执行自动审核服务...");

        //如果文章是4（人工审核或者为8）
        if (wmNews.getStatus() == 4 || wmNews.getStatus() == 8) {
            if (System.currentTimeMillis() <= wmNews.getPublishTime().getTime()) {
                sendDelayMessage(wmNews);
            } else {
                saveArticle(wmNews);
            }
        }

        //判断自媒体文章的状态
        if (wmNews.getStatus() == 1) {//1为提交之后待审核
            //调用阿里云审核文本内容
            //获取文章中的文本内容与图片内容
            Map<String, Object> map = getTextAndImagesFromContent(wmNews.getContent());

            //取出map集合中存储的文本内容，准备进行审核
            String text = (String) map.get("text");
            //取出内容中的图片
            List<String> images = (List<String>) map.get("images");

            //先进行本地敏感词的过滤
            boolean sensResult = checkSens(wmNews, text);
            if (!sensResult) return;//如果不为true直接结束方法

            //调用阿里云审核文本
            boolean textResult = checkText(wmNews, text);

            //判度，通过之后审核图片内容
            if (!textResult) return;//如果不为true直接结束方法

            //可能封面图片与内容图片不一致，需要全部添加到集合中
            List<ImageDto> coverImages = JSON.parseArray(wmNews.getImages(), ImageDto.class);
            for (ImageDto image : coverImages) {
                //判断
                if (!images.contains(image.getUrl())) {//如果内容中没有包含封面图片
                    images.add(image.getUrl());//就把封面图片的url地址存储到图片集合中
                }
            }

            //阿里云审核所有图片
            boolean imageResult = checkImage(wmNews, images);
            if (!imageResult) return;//如果不是true直接结束方法

            // 判断是否立刻发布文章，判断当前系统时间是否大于发布时间
            if (System.currentTimeMillis() <= wmNews.getPublishTime().getTime()) {
                //发送延迟消息
                sendDelayMessage(wmNews);

            } else {
                //保存文章到Article
                saveArticle(wmNews);
            }

            System.out.println(Thread.currentThread().getName() + "自动审核服务执行完成");

        }

    }

    private void sendDelayMessage(WmNews wmNews) {
        //如果未到时间修改状态为8 （8的意思是，审核通过了，等到时间再发布）
        wmNews.setStatus(8);
        wmNewsService.updateById(wmNews);
        //发送延迟消息
        RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque("article-publish");
        RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        //延迟长度为文章发布时间-当前系统时间
        long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
        delayedQueue.offer(wmNews, time, TimeUnit.MILLISECONDS);
    }

    @Autowired
    private IWmSensitiveService sensitiveService;

    /**
     * 本地敏感词的过滤
     *
     * @param wmNews
     * @param text
     * @return
     */
    private boolean checkSens(WmNews wmNews, String text) {
        if (SensitiveWordUtil.dictionaryMap.size() == 0) {
            //构建条件，查询出本地敏感词的文本
            LambdaQueryWrapper<WmSensitive> wrapper = new LambdaQueryWrapper<>();
            //查询出所有的敏感词
            wrapper.select(WmSensitive::getSensitives);
            List<String> words = sensitiveService.listObjs(wrapper, o -> o.toString());
            //调用工具类里的方法
            SensitiveWordUtil.initMap(words);
        }
        //审核标题、内容、标签中是否存在敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(wmNews.getTitle() + wmNews.getLabels() + text);
        //如果存在
        if (map.size() > 0) {
            //修改状态
            wmNews.setStatus(2);
            Set<String> keys = map.keySet();
            String join = String.join(" ", keys);
            wmNews.setReason("敏感词不通过：" + join);
            //修改WmNews
            wmNewsService.updateById(wmNews);

            //返回不成功
            return false;
        }
        return true;
    }

    @Autowired
    private IWmChannelService wmChannelService;

    @Autowired
    private ArticleFeign articleFeign;

    /**
     * 调用方法保存文章
     *
     * @param wmNews
     */
    private void saveArticle(WmNews wmNews) {

        //创建ArticleDao对象，准备填充数据
        ArticleDto dto = new ArticleDto();
        dto.setTitle(wmNews.getTitle());
        //根据WmNewsUserId取出文章的作者
        WmUser user = userService.getById(wmNews.getUserId());
        dto.setAuthorId(user.getApAuthorId());//文章作者id
        dto.setAuthorName(user.getName());//作者昵称
        dto.setChannelId(wmNews.getChannelId());//文章所属频道id

        //查询频道名称
        WmChannel channel = wmChannelService.getById(wmNews.getChannelId());
        dto.setChannelName(channel.getName());//频道名称
        dto.setLayout(wmNews.getType());//文章布局
        dto.setFlag(0);
        dto.setLabels(wmNews.getLabels());//标签名称
        dto.setPublishTime(new Date());//发布时间

        //前端显示的是图片地址，使用逗号分隔
        List<ImageDto> list = JSON.parseArray(wmNews.getImages(), ImageDto.class);
        List<String> images = new ArrayList<>();
        for (ImageDto imageDto : list) {
            images.add(imageDto.getUrl());//添加到集合
        }

        // 将集合转变成逗号分隔的字符串
        String join = String.join(",", images);
        dto.setImages(join);
        dto.setContent(wmNews.getContent());
        ResponseResult<Long> longResponseResult = articleFeign.saveArticle(dto);
        //如果远程添加成功
        if (longResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            //返回
            Long articleId = longResponseResult.getData();
            if (articleId != null) {
                //将文章id写回到WmNews中
                wmNews.setArticleId(articleId);
                //保存修改后的数据
                wmNews.setStatus(9);
                wmNewsService.updateById(wmNews);
            }
        }

    }

    @Autowired
    private MinIOService minIOService;

    //阿里云审核所有图片
    private boolean checkImage(WmNews wmNews, List<String> images) {
        boolean result = false;

        //判度，如果图片为空直接返回
        if (images.size() == 0) {
            return true;
        }
        //先从minio中下载图片到本地
        try {
            List<byte[]> imageList = new ArrayList<>();
            // minio服务部署在内网,需要先下载然后去阿里云审核
            for (String image : images) {
                if (!StringUtils.isEmpty(image)) {
                    InputStream inputStream = minIOService.download(image);
                    // 流转字节数组
                    byte[] bytes = IOUtils.toByteArray(inputStream);
                    imageList.add(bytes);
                }
            }
            //审核
            Map map = imageScan.imageScan(imageList);
            //判度结果
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass":
                    //审核通过
                    result = true;
                    break;
                case "block":
                    //审核不通过
                    //修改wmnews的状态
                    wmNews.setStatus(2);
                    //记录具体原因
                    wmNews.setReason("阿里云图片审核不通过" + map.get("label"));
                    //修改状态
                    wmNewsService.updateById(wmNews);
                    break;
                case "review":
                    //需要人工审核
                    //修改WmNews的状态
                    wmNews.setStatus(3);
                    //修改状态
                    wmNewsService.updateById(wmNews);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    //阿里云审核文本
    private boolean checkText(WmNews wmNews, String text) {
        boolean result = false;
        //取出wmnews中的标题与标签
        text = wmNews.getTitle() + wmNews.getLabels();

        //进行审核
        try {
            Map map = textScan.greenTextScan(text);
            //判断结果
            String suggestion = (String) map.get("suggestion");

            switch (suggestion) {
                case "pass":
                    //审核通过
                    result = true;
                    break;
                case "block":
                    //审核不通过
                    //修改wmnews的状态
                    wmNews.setStatus(2);
                    //记录具体原因
                    wmNews.setReason("阿里云文字审核不通过" + map.get("label"));
                    //修改状态
                    wmNewsService.updateById(wmNews);
                    break;
                case "review":
                    //需要人工审核
                    //修改wmnews的状态
                    wmNews.setStatus(3);
                    //修改状态
                    wmNewsService.updateById(wmNews);
                    break;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;

    }

    //获取文章中的文本内容与图片内容
    private Map<String, Object> getTextAndImagesFromContent(String content) {
        //准备集合，返回
        Map<String, Object> map = new HashMap<>();
        //准备将文本内容存放到sb中
        StringBuilder sb = new StringBuilder();
        //准备图片集合，存储图片
        List<String> images = new ArrayList<>();

        //取出content中的内容
        List<ContentDto> dtos = JSON.parseArray(content, ContentDto.class);
        for (ContentDto dto : dtos) {
            //判断取出文本
            if (dto.getType().equals("text")) {
                sb.append(dto.getValue());//存入到sb中
            } else {//代表是图片
                //添加到图片集合
                images.add(dto.getValue());
            }
        }
        map.put("text", sb.toString());
        map.put("images", images);
        return map;

    }
}
